import { useUserStore } from '@/store'
import storage from '../utils/storage'
import config from '@/config/index'
const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'
const whiteApiList = ['/api/login/mobile', '/api/login', '/api/register/verify', '/api/register/reset']

const TIMEOUT = 1000
/// 添加拦截器，拦截器配置
const httpInterceptor = {
  /// 拦截器按触发
  invoke(options: UniApp.RequestOptions) {
    // 加载loading
    uni.showLoading({
      title: '加载中...',
    })
    /// 非http开头需要拼接地址
    if (!options.url.startsWith('http')) {
      options.url = `${config.base}${options.url}`
    }
    options.timeout = TIMEOUT
    /// 添加请求头标识
    options.header = {
      'request-client': 'wechart-app',
      ...options.header,
    }
    const token = storage.getStorage('token')
    // 当本地没有token，并且接口地址没在白名单内，一律跳转登录页面
    if (!token && !whiteApiList.includes(options.url)) {
      // 跳转登录页面
      uni.hideLoading()
      return false
    }
    if (token) {
      options.header.Authorization = token
    }
  },
  success() {
    // 请求成功后，修改code值为1
    uni.hideLoading()
  },
  fail() {
    console.log('interceptor-fail')
    uni.hideLoading()
  },
  complete() {
    console.log('interceptor-complete')
    uni.hideLoading()
  },
}
// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
/**
 * 请求函数
 * @param  UniApp.RequestOptions
 * @returns Promise
 *  1. 返回 Promise 对象
 *  2. 获取数据成功
 *    2.1 提取核心数据 res.data
 *    2.2 添加类型，支持泛型
 *  3. 获取数据失败
 *    3.1 401错误  -> 清理用户信息，跳转到登录页
 *    3.2 其他错误 -> 根据后端错误信息轻提示
 *    3.3 网络错误 -> 提示用户换网络
 */
type Response<T> = {
  code: string
  msg: string
  result: T
}

export const http = <T>(options: UniApp.RequestOptions) => {
  return new Promise<Response<T>>((resolve, reject) => {
    uni.request({
      ...options,
      success(res) {
        // 状态码 2xx， axios 就是这样设计的
        if (res.statusCode >= 200 && res.statusCode < 300) {
          // 2.1 提取核心数据 res.data, 因为Promise需要返回的类型是Response<T>
          /// resolve也需要断言为 Response<T> 类型
          resolve(res.data as Response<T>)
        } else if (res.statusCode === 401) {
          // 401错误  -> 清理用户信息，跳转到登录页
          const userStore = useUserStore()
          userStore.clearUser()
          uni.navigateTo({ url: '/pages/login/login' })
          reject(res)
        } else {
          // 其他错误 -> 根据后端错误信息轻提示
          uni.showToast({
            icon: 'none',
            title: (res.data as Response<T>).msg || '请求错误',
          })
          reject(res)
        }
      },
      // 响应失败
      fail(err: UniApp.GeneralCallbackResult) {
        console.log(err)
        if (err.errMsg.indexOf('request:fail') !== -1) {
          wx.showToast({
            title: '网络异常',
            icon: 'error',
            duration: 2000,
          })
        } else {
          wx.showToast({
            title: '未知异常',
            duration: 2000,
          })
        }
        reject(err)
      },
      // 不管成功还是失败都会执行
      complete() {},
    })
  })
}

// 生成请求key
function generateReqKey(config: UniApp.RequestOptions) {
  const { method, url, data } = config
  return [method, url, JSON.stringify(data), JSON.stringify(data)].join('&')
}
// 对象转字url格式
function objToPathStr(val: object) {
  let str = ''
  for (const key in val) {
    str += key + '=' + (val[key] + '') + '&'
  }
  str = str.substring(0, str.length - 1)
  return str
}
